package list.impl;

import list.List;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * User: Vitalii Serdiuk
 * Date: 27.11.13 14:40
 */
public class SinglyLinkedList<T> implements List<T> {
    private Node head;
    private int size;

    public SinglyLinkedList() {
        head = null;
        size = 0;
    }

    public SinglyLinkedList(Node<T> head) {
        this.head = head;
        Node temp = head;
        int i;

        for( i=0; temp!=null;i++)
            temp = temp.getNext();

        this.size = i;
    }

    public void add(T data) {
        if (size == 0) {
            head = new Node<T>(data);
        } else {
            Node<T> newNode = new Node<T>(data);
            newNode.setNext(head);
            head = newNode;
        }
        size++;
    }

    public void delete(T data) {
        Node curNode = head;
        Node prevNode = null;

        while (!curNode.getData().equals(data)) {
            prevNode = curNode;
            curNode = curNode.getNext();
            if(curNode==null) throw new NoSuchElementException();
        }

        if (curNode.equals(head)) {
            head = curNode.getNext();
        } else {
            assert prevNode != null;
            prevNode.setNext(curNode.getNext());
        }
        size--;
    }

    public boolean contains(T data){
        Node curNode = head;
        while (curNode.getData().equals(data)) {
            curNode = curNode.getNext();
            if(curNode.getData()==null) return false;
        }
        return true;
    }

    public int size(){
        return size;
    }

    public void deleteAll(){
        head = null;
        size = 0;
    }

    public Iterator iterator(){
        return new Iterator(){
            private Node curNode = head;

            @Override
            public boolean hasNext() {
                return curNode!=null;
            }

            @Override
            public Object next() {
                Object result = curNode.getData();
                curNode = curNode.getNext();
                return result;
            }

            @Override
            public void remove() {
                delete((T) curNode.getData());
            }
        };
    }

    public void print() {
        Node node = head;
        System.out.print("SinglyLinkedList:");
        while (node != null) {
            System.out.print(" " + node.getData());
            node = node.getNext();
        }
        System.out.print(".");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof SinglyLinkedList)) return false;

        SinglyLinkedList that = (SinglyLinkedList) o;

        if (size != that.size) return false;
        return !(head != null ? !head.equals(that.head) : that.head != null);

    }

    @Override
    public int hashCode() {
        int result = head != null ? head.hashCode() : 0;
        result = 31 * result + size;
        return result;
    }
}
